function! api#init#buffer() abort
	let s:buffer = bufnr('*Messages*')
	if s:buffer < 0
		let s:buffer = bufnr('*Messages*', 1)
		setlocal buftype=nofile
		setlocal bufhidden=hide
		setlocal noswapfile
		setlocal buflisted
	endif
	return s:buffer
endfunction

function! api#init#show_buffer(...) abort
	if a:0 < 1
		let buffer = api#init#buffer()
	else
		let buffer = a:1
	endif
	let window = bufwinnr(buffer)
	if window < 0
		exec 'sbuffer ' . buffer
	else
		exec window . 'wincmd w'
	endif
endfunction

function! api#init#info(message) abort
	let current = bufnr('%')
	let window = bufwinnr(current)
	let buffer = api#init#buffer()
	let failed = appendbufline(buffer, '$', 'INFO: ' . a:message)
	call api#init#show_buffer(buffer)
	exec window . 'wincmd w'
endfunction

function! api#init#list_plugins() abort
	if !isdirectory(g:packdir)
		echom 'making gitee.com local directory ' . g:packdir
		call mkdir(g:packdir, "p")
	endif
	let plugins = glob(g:packdir . '/*', 1, 1)
	if !exists('&packpath')
		let &rtp = extend(split(&rtp), plugins)
	endif
	return plugins->map("fnamemodify(v:val, ':t')")
endfunction

function! api#init#update_all() abort
	let installed_plugins = api#init#list_plugins()
	for plugin in installed_plugins
		call api#init#update(plugin)
	endfor
endfunction

function! api#init#update(name) abort
	let repo = g:packdir . '/' . a:name
	if isdirectory(repo)
		exe 'set runtimepath+=' . repo
		call api#init#run('git pull ', repo, s:buffer)
	endif
endfunction

function! api#init#install(name) abort
	let g:url_prefix = get(g:, 'url_prefix', 'https://gitee.com/BIT_chenxinliang/')
	let repo = g:packdir . '/' . a:name
	let url = g:url_prefix . a:name
	if isdirectory(repo)
		call api#init#update(a:name)
	else
		call api#init#run('git clone' . url, g:packdir, s:buffer)
	endif
endfunction

let s:line = 0
function! api#init#message(job, message) abort
	let s:line = s:line + 1
	echom s:line . ' - ' . a:message
endfunction

function! api#init#on_exit(job, status) abort
	let options = job_info(a:job)
	if a:status == "fail"
		return
		echohl Error
		let cmdline = join(options.cmd, ' ')
		echoerr 'job ' . a:job . ' failed: ' . cmdline
		echoerr options
		echohl None
	else
		let output = has_key(options, 'out_buf') ? options.out_buf : s:buffer
		let lines = getbufline(output, 1, "$")
		if bufwinnr(output) < 0 " 缓冲区不可见
			if !empty(lines)
				exec 'sbuffer ' . output
			endif
		else
			if empty(lines)
				exec bufwinnr(output) . 'wincmd c'
			endif
		endif
	endif
endfunction

function! api#init#run(cmdline, directory, buffer) abort
	let prefer_asyncrun = get(g:, 'prefer_asyncrun', 0)
	if exists(':AsyncRun') && prefer_asyncrun
		exe 'AsyncRun -cwd=' . a:directory . ' ' . a:cmdline
	else
		let job = job_start(a:cmdline, {
					\ "cwd" 	: a:directory              ,
					\ "in_io"	: "null" 		           ,
					\ "out_buf" : a:buffer 		           ,
					\ "err_cb"  : function('api#init#message') ,
					\ "exit_cb" : function('api#init#on_exit')
					\ })
	endif
endfunction
